"""
    闭包
    装饰器
    类 遵循大驼峰命名法
"""
from functools import wraps
"""
    闭包
    1：函数嵌套
    2：内部函数使用外部函数局部变量
    3：外层函数返回值是内层函数的函数名
"""
def outter_func():
    num =  10
    def inner_func():
        print(num)
    return inner_func
outter_func()() # >>> 10

def outter_func2(a):
    def inner_func(b):
        return a + b
    return inner_func
ot = outter_func2(10)
print(ot(20)) # >>> 30
print(ot(30)) # >>> 40

"""
    装饰器@  支持多个
"""
def register_wrapper(func):
    def wrapper(*args, **kwargs):
        print("执行用户注册")
        return func(*args, **kwargs)
    print("register_wrapper", '执行')
    return wrapper

def register_wrapper1(func):
    def wrapper(*args, **kwargs):
        print("执行用户注册1" ,args)
        return func(*args, **kwargs)

    print("register_wrapper1", '执行')
    return wrapper

def register_wrapper2(func):
    @wraps(func)  # 保留原始函数元信息
    def wrapper(*args, **kwargs):
        print("执行用户注册2" ,args)
        return func(*args, **kwargs)
    return wrapper

def my_wraps(original_func):
    print("my_wraps 外层执行")
    def wrapper(decorator_func):
        print("my_wraps 内层执行")
        #decorator_func.__name__ = original_func.__name__
        #decorator_func.__doc__ = original_func.__doc__
        return decorator_func
    return wrapper



#嵌套注解
def register_wrapper_w(method):
    print("register_wrapper_w 外层执行")
    def decorator(func):
        print("register_wrapper_w 内层执行")
        @my_wraps(func)   # 保留原始函数元信息
        def wrapper(*args, **kwargs):
            print("执行用户注册3", args)
            return func(*args, **kwargs)
        return wrapper
    return decorator


#
# def my_wraps(original_func):
#     print(f"【阶段1】my_wraps 定义装饰器（原始函数: ）")
#
#     def decorator(wrapper_func):
#         print(f"【阶段2】decorator 包装（包装函数: ）")
#
#         def enhanced_wrapper(*args, **kwargs):
#             print(f"【阶段3】enhanced_wrapper 被调用时")
#             return wrapper_func(*args, **kwargs)
#
#         # 复制元数据
#         #enhanced_wrapper.__name__ = original_func.__name__
#         return enhanced_wrapper
#
#     return decorator

@register_wrapper
@register_wrapper1
@register_wrapper2
@register_wrapper_w("注册")
@my_wraps("注册")
#@my_wraps("注册1")
def add(a, b):
    return a + b
print(add(10, 20)) # >>> 执行用户注册  执行用户注册1 30

print('=========================================================')

def log_activity(activity_name):
    def decorator(func):
        # 尝试注释/取消注释下面这行看区别
        @my_wraps(func)
        def wrapper(*args, **kwargs):
            print(f"开始活动: {activity_name}")
            result = func(*args, **kwargs)
            print(f"完成活动: {activity_name}")
            return result
        return wrapper
    return decorator

@log_activity("用户注册")
def register_user(username, password):
    """这是注册函数的文档"""
    print("用户注册成功", username, password)

# 测试
register_user(username="lizme", password="123456")
print("函数名:", register_user.__name__)      # 有@my_wraps: register_user；没有: wrapper
print("文档字符串:", register_user.__doc__)  # 有@my_wraps: 这是...；没有: None

print('=========================================================')

"""
    类
    __str__ 如果一个方法名以双下划线开头且以双下划线结尾（例如__test__），它通常被识别为Python的特殊方法之一（也称为魔术方法）)
"""
class MathClass:
    a, b , a1 = 0, 0, 'XX'  #静态方法 类似java static
    __desc = "这是一个私有类描述"
    def __init__(self, a, b):  ##构造函数
        self.a = a
        self.b = b
        print(f"构造器初始化 a = {self.a} , b =  {self.b}") # >>> 构造器初始化 a = 1 , b =  2

    def t1(self):
        print("这是一个MathClass 的 t1方法")

    def get_desc(self):
        #return MathClass.__desc
        return self.__desc
    def __del__(self): ##析构函数
        print("析构函数执行，数据释放")

    # 定义__add方法
    def __test(self):
        print("__test执行")

    def add(self):
        return self.a + self.b
    def sub(self):
        return self.a - self.b
    def mul(self):
        return self.a * self.b
    def div(self):
        return self.a / self.b

cls = MathClass(1 ,2)
cls2 = MathClass(3 ,4)
print("MathClass.a", MathClass.a) # >>> MathClass.a 0
print(cls.a1)   # >>> XX
print(cls2.a1)   # >>> XX
MathClass.a1 = 'XXX'
print(cls.a1)   # >>> XXX
print(cls2.a1)   # >>> XXX
print(cls.a)    # >>> 1
print(cls.add()) # >>> 3
##print(cls.__desc)  # >>> AttributeError: 'MathClass' object has no attribute '__desc'
print(cls.get_desc()) # >>> 这是一个私有类描述
##cls.__test__() # >>> 'MathClass' object has no attribute '__test'


class SubClass(MathClass):  # class C(A, B): 多继承写法
    sa = 100
    def __new__(cls, *args, **kwargs):
        print("new 方法执行，分配内存空间")
        return super().__new__(cls)
    def __init__(self, a, b):
       super().__init__(a, b)
    def eat(self):
        super().t1()  # >>> 这是一个MathClass 的 t1方法
        print("吃饭")
    @classmethod
    def cls_method(cls):
        print(cls)  # class  <class '__main__.SubClass'>
        print("这是个类方法", "当前类有属性" , cls.sa)
    @staticmethod
    def static_method():
        print("这是个静态方法", "当前类有属性" , SubClass.sa)
sub = SubClass(1 , 2)
sub.t1()

print(dir(object))
print(SubClass.__mro__) # >>> (<class '__main__.SubClass'>, <class '__main__.MathClass'>, <class 'object'>)
SubClass.cls_method() # >>> 这是个类方法
SubClass.static_method() # >>> 这是个类方法

